import time
import requests
import subprocess
import threading
import sys
import os
from typing import List, Optional


class NetworkConfig:
    """网络配置对象"""

    def __init__(self, name: str, password: str, need_auth: bool = False,
                 auth_url: str = None, auth_username: str = None,
                 auth_password: str = None, check_url: str = "http://www.baidu.com"):
        self.name = name
        self.password = password
        self.need_auth = need_auth
        self.auth_url = auth_url
        self.auth_username = auth_username
        self.auth_password = auth_password
        self.check_url = check_url


class WindowsNetworkManager:
    """Windows 专用网络管理器"""

    def __init__(self, network_configs: List[NetworkConfig]):
        self.network_configs = network_configs
        self.current_network = None
        self.is_running = False
        self.check_interval = 30

    def run_command(self, command):
        """执行系统命令并返回结果（修复编码问题）"""
        try:
            result = subprocess.run(
                command,
                capture_output=True,
                text=True,
                encoding='utf-8',
                errors='ignore',
                shell=True,
                timeout=10
            )
            return result.stdout
        except subprocess.TimeoutExpired:
            print(f"命令执行超时: {command}")
            return None
        except Exception as e:
            print(f"执行命令失败: {e}")
            return None

    def create_wifi_profile(self, network_config: NetworkConfig) -> bool:
        """创建 WiFi 配置文件（包含密码）"""
        try:
            # 创建 XML 配置文件
            profile_xml = f'''<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
    <name>{network_config.name}</name>
    <SSIDConfig>
        <SSID>
            <name>{network_config.name}</name>
        </SSID>
    </SSIDConfig>
    <connectionType>ESS</connectionType>
    <connectionMode>auto</connectionMode>
    <MSM>
        <security>
            <authEncryption>
                <authentication>WPA2PSK</authentication>
                <encryption>AES</encryption>
                <useOneX>false</useOneX>
            </authEncryption>
            <sharedKey>
                <keyType>passPhrase</keyType>
                <protected>false</protected>
                <keyMaterial>{network_config.password}</keyMaterial>
            </sharedKey>
        </security>
    </MSM>
</WLANProfile>'''

            # 将配置文件保存到临时文件
            profile_path = f"C:\\temp\\{network_config.name}.xml"
            os.makedirs("C:\\temp", exist_ok=True)

            with open(profile_path, 'w', encoding='utf-8') as f:
                f.write(profile_xml)

            # 添加配置文件到系统
            command = f'netsh wlan add profile filename="{profile_path}"'
            output = self.run_command(command)

            if output and "已添加到接口" in output:
                print(f"已为网络 {network_config.name} 创建配置文件")
                # 清理临时文件
                try:
                    os.remove(profile_path)
                except:
                    pass
                return True
            else:
                print(f"创建网络配置文件失败: {output}")
                return False

        except Exception as e:
            print(f"创建 WiFi 配置文件时发生错误: {e}")
            return False

    def check_profile_exists(self, ssid: str) -> bool:
        """检查是否已存在该网络的配置文件"""
        command = f'netsh wlan show profiles name="{ssid}"'
        output = self.run_command(command)
        return output and "用户配置文件" in output

    def scan_available_networks(self) -> List[str]:
        """扫描可用的 WiFi 网络"""
        print("正在扫描可用网络...")
        output = self.run_command("netsh wlan show networks mode=bssid")
        available_networks = []

        if output:
            lines = output.split('\n')
            for line in lines:
                line = line.strip()
                if line.startswith('SSID') and 'BSSID' not in line and ':' in line:
                    parts = line.split(':', 1)
                    if len(parts) > 1:
                        ssid = parts[1].strip()
                        if ssid and ssid not in available_networks:
                            available_networks.append(ssid)

        print(f"扫描到 {len(available_networks)} 个可用网络: {available_networks}")
        return available_networks

    def get_current_network(self) -> Optional[str]:
        """获取当前连接的 WiFi 网络名称"""
        output = self.run_command("netsh wlan show interfaces")

        if output:
            lines = output.split('\n')
            for line in lines:
                line = line.strip()
                if line.startswith('SSID') and 'BSSID' not in line and ':' in line:
                    parts = line.split(':', 1)
                    if len(parts) > 1:
                        ssid = parts[1].strip()
                        if ssid and ssid != "":
                            return ssid
        return "未连接"

    def disconnect_wifi(self) -> bool:
        """断开当前 WiFi 连接"""
        print("正在断开当前 WiFi 连接...")
        output = self.run_command("netsh wlan disconnect")
        time.sleep(3)
        return True

    def connect_to_network(self, network_config: NetworkConfig) -> bool:
        """连接到指定 WiFi 网络（使用密码）"""
        print(f"正在尝试连接到网络: {network_config.name}")

        # 先检查网络是否可用
        available_networks = self.scan_available_networks()
        if network_config.name not in available_networks:
            print(f"网络 {network_config.name} 当前不可用")
            return False

        # 确保网络配置文件存在
        if not self.check_profile_exists(network_config.name):
            print(f"为网络 {network_config.name} 创建配置文件中...")
            if not self.create_wifi_profile(network_config):
                print(f"创建网络配置文件失败，无法连接 {network_config.name}")
                return False

        # 断开当前连接
        self.disconnect_wifi()
        time.sleep(2)

        # 连接到新网络
        command = f'netsh wlan connect name="{network_config.name}"'
        output = self.run_command(command)

        # 等待连接建立
        time.sleep(8)  # 增加等待时间，因为需要认证

        # 检查是否连接成功
        current_network = self.get_current_network()
        if current_network == network_config.name:
            print(f"已成功连接到网络: {network_config.name}")
            self.current_network = network_config

            # 检查网络连接状态
            if self.check_internet_connection(network_config.check_url):
                print(f"网络 {network_config.name} 连接成功且可以访问互联网")
                return True
            else:
                print(f"网络 {network_config.name} 已连接但无法访问互联网")
                if network_config.need_auth:
                    print("尝试进行网络认证...")
                    auth_result = self.perform_authentication(network_config)
                    if auth_result:
                        print("认证成功")
                    else:
                        print("认证失败")
                    return auth_result
                return True  # 即使不能上网，也认为连接成功
        else:
            print(f"连接网络 {network_config.name} 失败，当前网络: {current_network}")
            return False

    def check_internet_connection(self, check_url: str = None) -> bool:
        """检查互联网连接状态"""
        test_url = check_url or "http://www.baidu.com"
        try:
            print(f"正在检查网络连接: {test_url}")
            response = requests.get(test_url, timeout=10)
            connected = response.status_code == 200
            print(f"网络连接状态: {'正常' if connected else '异常'}")
            return connected
        except Exception as e:
            print(f"网络连接检查失败: {e}")
            return False

    def perform_authentication(self, network_config: NetworkConfig) -> bool:
        """执行网络认证"""
        if not network_config.need_auth or not network_config.auth_url:
            return True

        try:
            print(f"正在对网络 {network_config.name} 进行认证...")
            print(f"认证URL: {network_config.auth_url}")

            # 这里需要你根据实际的认证页面来补充认证逻辑
            # 示例认证代码（需要根据实际情况修改）：

            # 创建一个会话
            session = requests.Session()

            # 首先访问认证页面获取必要的token或cookie
            # response = session.get(network_config.auth_url, timeout=10)

            # 构造认证数据（根据实际认证页面调整）
            auth_data = {
                'username': network_config.auth_username,
                'password': network_config.auth_password,
                # 可能需要添加其他字段，如:
                # 'redirect_url': '',
                # 'submit': '登录'
            }

            # 发送认证请求
            # response = session.post(network_config.auth_url, data=auth_data, timeout=10)

            # 检查认证是否成功
            # if "认证成功" in response.text or response.status_code == 200:
            #     print(f"网络 {network_config.name} 认证成功")
            #     return True
            # else:
            #     print(f"网络 {network_config.name} 认证失败")
            #     return False

            print("认证逻辑待实现 - 当前跳过认证")
            return True  # 暂时返回True，避免影响连接流程

        except Exception as e:
            print(f"认证过程中发生错误: {e}")
            return False

    def delete_wifi_profile(self, ssid: str) -> bool:
        """删除 WiFi 配置文件"""
        try:
            command = f'netsh wlan delete profile name="{ssid}"'
            output = self.run_command(command)
            if output and "已从接口" in output:
                print(f"已删除网络配置文件: {ssid}")
                return True
            return False
        except Exception as e:
            print(f"删除网络配置文件失败: {e}")
            return False

    def auto_connect_to_available_network(self) -> bool:
        """自动连接到第一个可用的配置网络"""
        print("开始自动连接可用网络...")
        available_networks = self.scan_available_networks()

        print(f"配置的网络列表: {[config.name for config in self.network_configs]}")
        print(f"可用的网络列表: {available_networks}")

        for config in self.network_configs:
            if config.name in available_networks:
                print(f"尝试连接到配置网络: {config.name}")
                if self.connect_to_network(config):
                    return True
                else:
                    print(f"连接 {config.name} 失败，尝试下一个网络")

        print("所有配置网络均无法连接")
        return False

    def network_check_loop(self):
        """网络检查循环"""
        check_count = 0
        while self.is_running:
            try:
                check_count += 1
                print(f"\n=== 第 {check_count} 次网络检查 ===")

                current_network_name = self.get_current_network()
                print(f"当前网络: {current_network_name}")

                # 检查当前网络是否在配置列表中
                current_config = None
                for config in self.network_configs:
                    if config.name == current_network_name:
                        current_config = config
                        break

                if current_config is None:
                    # 当前网络不在配置列表中
                    print("当前网络不在配置列表中，尝试切换到配置网络...")
                    self.auto_connect_to_available_network()
                else:
                    # 检查互联网连接
                    if not self.check_internet_connection(current_config.check_url):
                        print("网络连接异常，尝试处理...")
                        if current_config.need_auth:
                            print("尝试重新认证...")
                            if self.perform_authentication(current_config):
                                print("认证成功")
                            else:
                                print("认证失败，尝试重新连接网络")
                                self.disconnect_wifi()
                                time.sleep(2)
                                self.connect_to_network(current_config)
                        else:
                            print("网络无法访问互联网，尝试重新连接")
                            self.disconnect_wifi()
                            time.sleep(2)
                            self.connect_to_network(current_config)
                    else:
                        print("网络连接正常")

                print(f"等待 {self.check_interval} 秒后再次检查...")

            except Exception as e:
                print(f"网络检查过程中发生错误: {e}")
                import traceback
                traceback.print_exc()

            time.sleep(self.check_interval)

    def start(self, check_interval: int = 30):
        """启动网络管理器"""
        self.check_interval = check_interval
        self.is_running = True

        print("启动 Windows 网络管理器...")
        print("=" * 50)

        # 初始连接
        self.auto_connect_to_available_network()

        # 启动监控线程
        monitor_thread = threading.Thread(target=self.network_check_loop)
        monitor_thread.daemon = True
        monitor_thread.start()

        print(f"网络管理器已启动，检查间隔: {check_interval}秒")
        print("按 Ctrl+C 停止程序")

    def stop(self):
        """停止网络管理器"""
        self.is_running = False
        print("网络管理器已停止")


def main():
    """主函数"""
    # 创建网络配置列表 - 请根据你的实际情况修改这些配置
    network_configs = [
        NetworkConfig(
            name="你的WiFi名称1",
            password="你的WiFi密码1",
            need_auth=False,
            check_url="http://www.baidu.com"
        ),
        NetworkConfig(
            name="你的WiFi名称2",
            password="你的WiFi密码2",
            need_auth=False,
            check_url="http://www.baidu.com"
        )
    ]

    # 检查是否有配置
    if not network_configs or network_configs[0].name == "你的WiFi名称1":
        print("请先修改 network_configs 中的 WiFi 配置！")
        print("1. 将 '你的WiFi名称1' 改为你的实际 WiFi 名称")
        print("2. 将 '你的WiFi密码1' 改为你的实际 WiFi 密码")
        return

    # 创建网络管理器
    manager = WindowsNetworkManager(network_configs)

    try:
        # 启动网络管理器
        manager.start(check_interval=30)

        # 保持主线程运行
        while True:
            time.sleep(1)

    except KeyboardInterrupt:
        print("\n接收到中断信号，正在停止程序...")
        manager.stop()


if __name__ == "__main__":
    main()